﻿using System;

namespace Effects.Effects.Tools
{
    /// <summary>
    ///  Base class for all ocsillators.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///      This class defines interface for all classes that implements some oscillator.
    ///      Amplitude (max value of oscilation) is expected to be value 1. It is not necessary to always fulfil this convention, but it makes different oscillators fully compatible.
    ///     </para>
    ///     <para>
    ///      Every ocillator stores it's current time. It can be accessed via Time property: <see cref="Oscillator.Time"/> This time is also used in Step method.
    ///     </para>
    /// </remarks>
    public class Oscillator
    {

        /// <summary>
        ///     Period of the oscilation.
        /// </summary>
        /// <remarks>
        ///     Member holds information about how long is one period. (i.e. time interval between two maximums)
        /// </remarks>
        protected double period;

        /// <summary>
        ///  Gets or sets the period of the oscillation.
        /// </summary>
        public virtual double Period
        {
            get { return period; }
            set { period = value; }
        }

        /// <summary>
        ///  Current time of oscillation system.
        /// </summary>
        protected double time;

        /// <summary>
        ///     Gets or sets current time of oscillator. 
        /// </summary>
        /// <remarks>
        ///     Class stores current time of an oscillation system. This time can be set via this property. This time is used (and change) when method Step is called.  
        /// </remarks>
        public virtual double Time
        {
            get { return time; }
            set { time = value; }
        }

        /// <summary>
        ///  Creates oscillator with zero period and time.
        /// </summary>
        public Oscillator()
        {
            this.period = 0;
            this.time = 0;
        }
        /// <summary>
        ///  Creates oscillator with given period and zero time
        /// </summary>
        /// <param name="period"> Period of an oscilator </param>
        public Oscillator(double period)
        {
            this.period = period;
            this.time = 0;
        }

        /// <summary>
        ///     Makes stepTime advance of oscillator's time and returns current value of oscillation
        /// </summary>
        /// <param name="stepTime"> Length of a step that oscillator advances in time. </param>
        /// <returns> Current value of an oscillator after the step.</returns>
        /// <remarks>
        ///     This method should be overrridden in concrete implementations. This implementation always returns value 1.
        /// </remarks>
        public virtual double Step(double stepTime)
        {
            return 1;
        }

        /// <summary>
        ///   Gets ocillator's value at given time.
        /// </summary>
        /// <param name="time"> time of the oscilation </param>
        /// <returns> Value at given time. </returns>
        /// <remarks>
        ///     This method should be overrridden in concrete implementations. This implementation always returns value 1.
        /// </remarks>
        public virtual double Amplitude(double time)
        {
            return 1;
        }
    }
}